package cn.study.zgm.nettyall.selector.selector;

import cn.study.zgm.nettyall.channel.ByteBufferUtil;
import lombok.extern.slf4j.Slf4j;

import javax.xml.stream.events.Characters;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * packageName cn.study.zgm.nettyall.selector.selector
 *
 * @author 你的名字
 * @version JDK 8
 * @className Server (此处以class为例)
 * @date 2025/2/25
 * @description TODO
 */
@Slf4j
public class Server {
    private static void split(ByteBuffer buffer) {
        // 切换为读模式
        buffer.flip();
        for (int i = 0; i < buffer.limit(); i++) {
            if (buffer.get(i)=='\n'){
                int length = i +1- buffer.position();
                byte[] bytes = new byte[length];
                buffer.get(bytes,0,length);
                ByteBuffer tempByteBuffer = ByteBuffer.wrap(bytes);
                ByteBufferUtil.debugAll(tempByteBuffer);
            }
        }
        // 切换为写模式
        buffer.compact();
    }

    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();
        // 创建一个服务端
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        // 将ssc channel注册到selector中去
        SelectionKey sscKey = ssc.register(selector, 0, null);
        log.error("设置key的属性为accept，接收客户端连接");
        sscKey.interestOps(SelectionKey.OP_ACCEPT);
        log.error("打印sscKey信息{}",sscKey);
        ssc.bind(new InetSocketAddress("127.0.0.1", 8081));

        while (true){
            selector.select();
            Iterator<SelectionKey> iterator = sscKey.selector().selectedKeys().iterator();
            while(iterator.hasNext()){
                SelectionKey key = iterator.next();
                iterator.remove();
                log.error("打印事件key{}",key);
                if (key.isAcceptable()){
                    ServerSocketChannel sscChannel = (ServerSocketChannel) key.channel();
                    log.error("服务器开始连接------------------------");
                    final SocketChannel scChannel = sscChannel.accept();//因为sscChanel第一次处理完后，就会将事件移除，但是不会从selectedKeys集合中移除，下一个读事件来的时候，获取连接为null，导致空指针异常
                    scChannel.configureBlocking(false);
                    log.error("服务器连接到{}--------------",scChannel);
                    ByteBuffer buffer = ByteBuffer.allocate(8);
                    final SelectionKey tempKey = scChannel.register(selector, 0, buffer);
                    tempKey.interestOps(SelectionKey.OP_READ);
//                    key.cancel();// 从selectedKey中移除
                }else if (key.isReadable()){
                    final ByteBuffer buffer =(ByteBuffer) key.attachment();
                    SocketChannel scChannel = (SocketChannel) key.channel();
                    // 如果客户端强制关闭连接（宕机或者其他原因关闭现有连接，则会报错），需要进行移除捕获
                    try{
                        log.error("服务器开始读取{}信息--------",scChannel);
                        // 如果read返回值为-1表示，读取客户端断开连接，需要进行判断返回值来进行处理
                        final int read = scChannel.read(buffer);
                        if (read >= 0){
                            split(buffer);
                            if (buffer.position()==buffer.limit()){
//                                ByteBufferUtil.debugRead(buffer);
                                final ByteBuffer twoByteBuffer = ByteBuffer.allocate(buffer.capacity() * 2);
                                buffer.flip();
                                twoByteBuffer.put(buffer);
                                key.attach(twoByteBuffer);
                              
                            }
                        }else if (read== -1){
                            key.cancel();
                            log.error("服务器与客户端{}断开连接",scChannel);
                        }
                        log.error("服务器开始读取信息结束----------------");
                    }catch (IOException e){
                        key.cancel();
                        e.printStackTrace();
                    }
                }


//                final SocketChannel sc = sscChannel.accept();
//            sc.register(selector,0,null);
            }
        }


    }
}
